#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <sys/mman.h>
#include "u_zach5.h"
#include "z5registers.h"

struct vertex {
	float x, y, z, r, g, b;
};
/*
struct vertex V[] = {
	40.0, 40.0, 128.0, 0.0, 0.0,
	500.0, 500.0, 255.0, 0.0, 0.0,
	0.0
};
*/
struct vertex V[] = {
	400.0, 100.0, 0.0, 255.0, 0.0, 0.0,
	500.0, 400.0, 0.0, 255.0, 0.0, 0.0,
	200.0, 600.0, 0.0, 255.0, 0.0, 0.0,
	0.0
};


draw_square()
{
	float drdy, dgdy, dbdy;

	//unsigned long value;
	drdy = (V[1].r - V[0].r)/(V[1].y - V[0].y);
	dgdy = (V[1].g - V[0].g)/(V[1].y - V[0].y);
	dbdy = (V[1].b - V[0].b)/(V[1].y - V[0].y);
	
	FIFOSYNC;
	U_WRITE_REG(R0, makecolor(V[0].r));
	U_WRITE_REG(G0, makecolor(V[0].g));
	U_WRITE_REG(B0, makecolor(V[0].b));
	
	U_WRITE_REG(dRdyDom, makecolor(drdy));
	U_WRITE_REG(dGdyDom, makecolor(dgdy));
	U_WRITE_REG(dBdyDom, makecolor(dbdy));
	
	U_WRITE_REG(RasterizerCfg, 0x40000000);
	U_WRITE_REG(XDom0, makecoord(V[0].x));
	U_WRITE_REG(dXDom, makecoord(0.0));
	
	U_WRITE_REG(XSub0, makecoord(V[1].x));
	U_WRITE_REG(dXSub, makecoord(1.0));
	U_WRITE_REG(Y0, makecoord(V[0].y));
	
	FIFOSYNC;
	U_WRITE_REG(dY,makecoord(1.0));
	U_WRITE_REG(Count, (int)(fabs(V[0].y - V[1].y)) << 18);
	
	FIFOSYNC;
	U_WRITE_REG(Render,RENDER_TRAPEZOID_SPC);
}

drawTriangle()
{
	float drdy, dgdy, dbdy, drdx,dgdx,dbdx,dx02,dx01,dx12;
	FILE *fd;
	
	int a = fabs(((V[0].x-V[2].x)*(V[1].y-V[2].y))-((V[1].x-V[2].x)*(V[0].y-V[2].y)));
	
	//y - gradient to get colors
	drdy = (V[2].r - V[0].r)/(V[2].y - V[0].y);
	dgdy = (V[2].g - V[0].g)/(V[2].y - V[0].y);
	dbdy = (V[2].b - V[0].b)/(V[2].y - V[0].y);
	//x-gradient to get colors
        drdx = ((V[0].r-V[2].r)*((V[1].y-V[2].y)/a))-((V[1].r-V[2].r)*((V[0].y-V[2].y)/a));
	dgdx = ((V[0].g-V[2].g)*((V[1].y-V[2].y)/a))-((V[1].g-V[2].g)*((V[0].y-V[2].y)/a));
	dbdx = ((V[0].b-V[2].b)*((V[1].y-V[2].y)/a))-((V[1].b-V[2].b)*((V[0].y-V[2].y)/a));
	// slopes of all three sides of all triangle
	dx02 = ((V[2].x-V[0].x)/(V[2].y-V[0].y));
	dx01 = ((V[1].x-V[0].x)/(V[1].y-V[0].y));
	dx12 = ((V[2].x-V[1].x)/(V[2].y-V[1].y));
	
	//sync up
	FIFOSYNC;
	//initialize (RGB) to color of the first point
	U_WRITE_REG(R0, makecolor(V[0].r));
	U_WRITE_REG(G0, makecolor(V[0].g));
	U_WRITE_REG(B0, makecolor(V[0].b));
	
	//color of the dominant edge
	U_WRITE_REG(dRdyDom, makecolor(drdy));
	U_WRITE_REG(dGdyDom,makecolor(dgdy));
	U_WRITE_REG(dBdyDom, makecolor(dbdy));
		
	U_WRITE_REG(dRdx, makecolor(drdx));
	U_WRITE_REG(dGdx, makecolor(dgdx));
	U_WRITE_REG(dBdx, makecolor(dbdx));


	U_WRITE_REG(ZStartU, makecoord(0.0));
	
	U_WRITE_REG(ZStartL, makecoord(0.0));
	U_WRITE_REG(dZdyDomU, makecoord(0.0));
	U_WRITE_REG(dZdyDomL, makecoord(0.0));
	U_WRITE_REG(dZdxU, makecoord(0.0));
	U_WRITE_REG(dZdxL, makecoord(0.0));
	U_WRITE_REG(RasterizerCfg, 0x40000000);
	
	U_WRITE_REG(XDom0, makecoord(V[0].x));
	U_WRITE_REG(dXDom, makecoord(dx02));
	
	U_WRITE_REG(XSub0, makecoord(V[0].x));
	U_WRITE_REG(dXSub, makecoord(dx01));

	U_WRITE_REG(Y0, makecoord(V[0].y));
	
	U_WRITE_REG(dY,makecoord(1.0));
 	U_WRITE_REG(Count,(int)(fabs(V[0].y-V[1].y))<<18);
	
	U_WRITE_REG(Render,RENDER_TRAPEZOID_SPC);
	

//	U_WRITE_REG(XDom0, makecoord(V[0].x));

//	U_WRITE_REG(dXDom, makecoord(dx02));
	
	U_WRITE_REG(XSub0, makecoord(V[1].x));
	U_WRITE_REG(dXSub, makecoord(dx12));

	U_WRITE_REG(ContinueNewSub,(int)(fabs(V[1].y-V[2].y))<<18);

	
//	U_WRITE_REG(Y0, makecoord(V[1].y));
//	U_WRITE_REG(dY,makecoord(1.0));
// 	U_WRITE_REG(Count,(int)(fabs(V[2].y-V[1].y))<<18);

//	U_WRITE_REG(XSub0, makecoord(V[1].x));
//	U_WRITE_REG(RasterizerCfg, 0x4000000);
	
	//FIFOSYNC;
	//U_WRITE_REG(Render,RENDER_TRAPEZOID_SPC);
}


int main()
{
	int fd, result, count;
	
	fd = open("/dev/zach5", O_RDWR);
	zach5.control_base = mmap(0, ZACH5_CONTROL_SIZE, PROT_READ |
		PROT_WRITE, MAP_SHARED, fd, 0);
	result = ioctl(fd, VMODE, V_800x600_75Hz);
	sleep(5);
        //draw_square();
	drawTriangle();
	sleep(5);
	ioctl(fd, VMODE, V_OFF);
	close(fd);
	return 0;
}

